#pragma once

#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <queue>
#include <mutex>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <string.h>
#include <condition_variable>
#include <unordered_map>
#include <memory>
#include <sys/signalfd.h>
#include <signal.h>
#include <utility>
#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/metadata.h>
#include <cppconn/exception.h>
// #include <mysql/mysql.h>

using std::thread;
using std::cout;
using std::cerr;
using std::endl;
using std::mutex;
using std::unique_lock;
using std::condition_variable;
using std::queue;
using std::vector;
using std::unordered_map;
using std::string;
using std::shared_ptr;

class Parser;
using ParserPtr = Parser *;

constexpr static int EPOLL_EVENT_LEN = 128;
constexpr static int PROTOCOL_BUF_LEN = 4096;

constexpr static char *MYSQL_HOST_ = "localhost";
constexpr static short MYSQL_PORT_ = 3306;
constexpr static char *MYSQL_USER_ = "root";
constexpr static char *MYSQL_PWD_ = "123";
constexpr static char *MYSQL_DB_ = "terminal_cloud_netdisk";

#define DEBUG
#define ERR_CHECK(var, val, msg) if(val == var) {perror(msg); return;}
#define ERR_CHECK_RETURN(var, val, msg) if(val == var) {perror(msg); return -1;}

class NoCopyable{
public:
    NoCopyable(){}
private:
    NoCopyable(const NoCopyable &elm){}
    NoCopyable operator=(const NoCopyable &elm){return elm;}
};

enum class Behavior: short{
    REGISTER,   // 注册
    LOGIN,      // 登录
    LS,
    CD,
    PWD,
    MKDIR,
    REMOVE,     // 删除文件或非空文件夹
    TOKEN,
    GETS,       // 下载文件
    PUTS,       // 上传文件
    TRANSFER,   // 传输文件
};

// 服务端与客户端通信的协议
struct Protocol{
    enum Behavior behavior_;    // 行为
    char buf_[PROTOCOL_BUF_LEN]; 
};

struct User{
    int id;
    int uid;
    int code;
    int precode;
    string fname;
    string md5sum;
};

struct File{
    int fid;
    string fname;
    string md5sum;
    short linked;
};

struct VirtualDirec{
    int uid;
    string uname;
    string upwd;
    string encrypt;
    string root_path;
};